using System;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Threading;

namespace WpfApp_ChenxiConsole.TCP
{
    /// <summary>
    /// TCP客户端管理器，负责处理TCP连接、消息接收和断开连接的逻辑
    /// </summary>
    public class TcpClientManager
    {
        private TcpClient? client;
        private bool isReceiving = false;
        private Action<string, string>? onMessageReceived; // 回调函数，用于通知接收到的消息
        private Action? onConnectionClosed; // 回调函数，用于通知连接关闭
        private Action<Brush>? onUpdateLinkPointerColor; // 回调函数，用于更新连接状态指示器颜色
        private Dispatcher? dispatcher; // UI线程的Dispatcher

        /// <summary>
        /// 初始化TcpClientManager
        /// </summary>
        /// <param name="dispatcher">UI线程的Dispatcher</param>
        /// <param name="onMessageReceived">消息接收回调函数</param>
        /// <param name="onConnectionClosed">连接关闭回调函数</param>
        /// <param name="onUpdateLinkPointerColor">更新连接状态指示器颜色的回调函数</param>
        public TcpClientManager(
            Dispatcher dispatcher,
            Action<string, string> onMessageReceived,
            Action onConnectionClosed,
            Action<Brush> onUpdateLinkPointerColor
        )
        {
            this.dispatcher = dispatcher;
            this.onMessageReceived = onMessageReceived;
            this.onConnectionClosed = onConnectionClosed;
            this.onUpdateLinkPointerColor = onUpdateLinkPointerColor;
        }

        /// <summary>
        /// 连接到指定的IP地址和端口
        /// </summary>
        /// <param name="ipAddress">目标IP地址</param>
        /// <param name="port">目标端口号</param>
        /// <returns>连接结果</returns>
        public async Task<bool> ConnectAsync(string ipAddress, int port)
        {
            try
            {
                client = new TcpClient();
                await client.ConnectAsync(ipAddress, port);
                
                // 更新连接状态指示器为红色
                dispatcher?.Invoke(() =>
                {
                    onUpdateLinkPointerColor?.Invoke(Brushes.Red);
                });
                
                // 开始接收消息
                StartReceivingMessages();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 开始接收消息的异步任务
        /// </summary>
        private async void StartReceivingMessages()
        {
            if (client == null || isReceiving)
                return;

            isReceiving = true;
            try
            {
                NetworkStream stream = client.GetStream();
                byte[] buffer = new byte[1024];
                int bytesRead;

                // 循环接收消息，直到连接关闭
                while ((bytesRead = await stream.ReadAsync(buffer.AsMemory(0, buffer.Length))) > 0)
                {
                    // 将接收到的字节转换为字符串
                    string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                    // 调用消息过滤器过滤消息
                    MessageFilter.FilterMessage(message);

                    // 通过回调函数通知接收到的消息
                    onMessageReceived?.Invoke($"{message}", "收>> ");
                }

                // 连接关闭
                OnConnectionClosed();
            }
            catch (Exception ex)
            {
                // 判断是否是用户主动断开连接导致的异常
                string errorMessage = ex.Message;
                if (!errorMessage.Contains("已中止 I/O 操作"))
                {
                    // 只显示非主动断开连接导致的错误信息
                    onMessageReceived?.Invoke($"接收消息错误：{ex.Message}\n", "错误");
                }
                OnConnectionClosed();
            }
            finally
            {
                isReceiving = false;
            }
        }

        /// <summary>
        /// 处理连接关闭的逻辑
        /// </summary>
        private void OnConnectionClosed()
        {
            if (client != null)
            {
                if (client.Connected)
                {
                    client.Close();
                }
                client = null;
            }

            // 更新UI状态
            dispatcher?.Invoke(() =>
            {
                onUpdateLinkPointerColor?.Invoke(Brushes.Transparent);
                onConnectionClosed?.Invoke();
            });
        }

        /// <summary>
        /// 断开TCP连接
        /// </summary>
        public void Disconnect()
        {
            if (client != null && client.Connected)
            {
                try
                {
                    client.Close();
                }
                catch (Exception)
                {
                    // 忽略断开连接时的异常
                }
                finally
                {
                    client = null;
                }
            }

            // 更新UI状态
            dispatcher?.Invoke(() =>
            {
                onUpdateLinkPointerColor?.Invoke(Brushes.Transparent);
                onConnectionClosed?.Invoke();
            });
        }

        /// <summary>
        /// 获取当前连接状态
        /// </summary>
        /// <returns>是否已连接</returns>
        public bool IsConnected()
        {
            return client != null && client.Connected;
        }
        
        /// <summary>
        /// 发送消息到TCP连接
        /// </summary>
        /// <param name="message">要发送的消息</param>
        /// <returns>发送是否成功</returns>
        public async Task<bool> SendMessageAsync(string message)
        {
            // 默认使用UTF-8编码
            return await SendMessageAsync(message, Encoding.UTF8);
        }
        
        /// <summary>
        /// 使用指定编码格式发送消息到TCP连接
        /// </summary>
        /// <param name="message">要发送的消息</param>
        /// <param name="encoding">要使用的编码格式</param>
        /// <returns>发送是否成功</returns>
        public async Task<bool> SendMessageAsync(string message, Encoding encoding)
        {
            if (client == null || !client.Connected)
            {
                return false;
            }
            
            try
            {
                NetworkStream stream = client.GetStream();
                byte[] data = encoding.GetBytes(message);
                await stream.WriteAsync(data, 0, data.Length);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}